/* //device/system/broncho-ril/reference-ril.c
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include <telephony/ril.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <alloca.h>
#include "atchannel.h"
#include "at_tok.h"
#include "ril_util.h"
#include <getopt.h>
#include <sys/socket.h>
#include "broncho-ril.h"
#include "cutils/properties.h"

#define LOG_TAG "RIL"
#include "broncho_log.h"

#define SIM_DSDS ((getSimId() == SIM_ID_DUAL) ? 2 : 1)

typedef struct _DevContext
{
	char*	baseband;
}DevContext;

static DevContext* devGetContext(RIL* thiz)
{
	DevContext* ctx = RIL_GetPrivInfo(thiz, "dev_ctx");
	if(ctx == NULL)
	{
		ctx = calloc(1, sizeof(DevContext));
		RIL_SetPrivInfo(thiz, ctx, "dev_ctx");
	}

	return ctx;
}

static char* getBaseband(RIL* thiz)
{
	ATResponse *p_response = NULL;
	char* version = NULL;

	if (ril_command_exec_singleline_for_result(thiz, "AT+CGMR", "Project Version:   ", &p_response))
	{
		at_line_scanf_string (p_response->p_intermediates->line, &version);
	}
	
	return strdup(version);
}

char* RIL_GetBaseband(RIL* thiz)
{
	DevContext* ctx = devGetContext(thiz);
	if(ctx->baseband == NULL)
	{
		ctx->baseband = getBaseband(thiz);
	}
	ALOGD("RIL_GetBaseband %s ", ctx->baseband);

	return ctx->baseband;
}

static void requestSetMute(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	char cmd[32] = {0};
	int mute = ((int*)data)[0];

	snprintf(cmd, 32, "AT+CMUT=%d", mute);

	ril_send_command(thiz, cmd, NULL);
	RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);

	return;
}

static void requestOemHookStrings(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, data, datalen);

	return;
}

static void requestOemHookRaw(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, data, datalen);
}

static void reqestQueryAvailableBandMode(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	int bands[] = {0, 1, 2, 4, 5, 6};

	RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, bands, sizeof (bands));

	return;
}

static void requestSetBandMode(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	int mode = 0;
	char cmd[32] = {0};
	int bands[] = {3, 3, 5, -1, 3, 3, 12};

	mode = ((int *)data)[0];

	snprintf (cmd, 32, "AT+CPBSE=%d", bands[mode]);
	if (ril_command_exec_for_result(thiz, cmd))
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}

	return;
}

static void requestBasebandVersion(RIL* thiz, void* data, size_t datalen, RIL_Token t)
{
	char* version = RIL_GetBaseband(thiz);
        RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS,
            version, sizeof(char *));
	
	return;

}

static void requestGetMute(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	int mute = 0;
	int result = 0;
	ATResponse *p_response = NULL;

	if(ril_command_exec_singleline_for_result(thiz, "AT+CMUT?", "+CMUT:", &p_response))
	{
		result = at_line_scanf_int(p_response->p_intermediates->line, &mute);
	}
	
	if (result)
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, &mute, sizeof(mute));
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	at_response_free (p_response);

	return;
}

/*
static void requestGetImeiSv(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	ATResponse* p_response = NULL;

	if(ril_command_exec_singleline_for_result(thiz, "AT+EGMR=0,9", "+EGMR:", &p_response))
	{
		char* sv = NULL;

		at_line_scanf_string(p_response->p_intermediates->line, &sv);
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, sv, sizeof(char*));
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}
	at_response_free (p_response);

	return;
}*/

static void requestGetImei(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	ATResponse *p_response = NULL;
	int err = 0;

        err = ril_send_command_numeric(thiz, "AT+CGSN", &p_response);
        if (err < 0 || p_response->success == 0) 
	{
           RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
        } 
	else 
	{
		char imei[PROPERTY_VALUE_MAX] = {0};
		property_get((getSimId() == SIM_ID_DUAL) ? "ro.imeino2" : "ro.imeino", imei, "");
		if(strcmp(imei, p_response->p_intermediates->line) && strlen(imei) == 15) 
		{
			ALOGD("get ro.imeino %s set it to modem", imei);
			char cmd[128] = {0};
			snprintf(cmd, 127, "AT+SGMR=%d,1,1,\"%s\"", getSimId() == SIM_ID_DUAL ? 1 : 0, imei);
			ril_send_command(thiz, cmd, NULL);
			RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS,
					imei, sizeof(char *));
		} 
		else
		{
			RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS,
					p_response->p_intermediates->line, sizeof(char *));
		}
	}
        at_response_free(p_response);
	
	return;
}

static int isRadioOn (RIL* thiz)
{
	int radio_on = 0;
	ATResponse *p_response = NULL;

	if (ril_command_exec_singleline_for_result(thiz, "AT+SFUN?", "+SFUN:", &p_response))
	{
		at_line_scanf_int (p_response->p_intermediates->line, &radio_on);
	}
	at_response_free(p_response);

	return radio_on == 1;
}

static void requestResetRadio(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	int result = 0;

	ril_command_exec_for_result(thiz, "ATH");
	if (ril_command_exec_full_for_result(thiz, "AT+SFUN=0", 20000))
	{
		RIL_SetRadioState(thiz, RADIO_STATE_OFF);
		if (ril_command_exec_full_for_result(thiz, "AT+SFUN=2", 20000))
		{
			RIL_SetRadioState(thiz, RADIO_STATE_SIM_NOT_READY);
			result = 1;
		}
	}

	if (result)
	{
		RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}

	return;
}

int RIL_initialize_dev (RIL* thiz)
{
	return 1;
}

static void requestRadioPower(RIL* thiz, void *data, size_t datalen, RIL_Token t)
{
	int onOff = 0;
	int State = 0;
	int success = 1;

        assert (datalen >= sizeof(int *));
        onOff = ((int *)data)[0];

	State = RIL_GetState(thiz);
        if (onOff == 0 && State != RADIO_STATE_OFF/* && isRadioOn(thiz)*/) 
	{
		//ril_command_exec_for_result(thiz, "ATH");
		if((success = ril_command_exec_full_for_result(thiz, "AT+SFUN=5", 20000)))
		{
                	RIL_SetRadioState(thiz, RADIO_STATE_OFF);
		}
        } 
	else if (onOff > 0 && State == RADIO_STATE_OFF/* && !isRadioOn(thiz)*/) 
	{
		if((success = ril_command_exec_full_for_result(thiz, "AT+SFUN=2", 20000)))
		{
			/* yinlijun add for spretrum bug, returns two "OK" */
			sleep(1);
                	RIL_SetRadioState(thiz, RADIO_STATE_SIM_NOT_READY);
		}
        }

	if (success)
	{
    	        RIL_onRequestComplete(thiz, t, RIL_E_SUCCESS, NULL, 0);
	}
	else
	{
		RIL_onRequestComplete(thiz, t, RIL_E_GENERIC_FAILURE, NULL, 0);
	}

	return;
}

int RIL_onUnsolicited_dev (RIL* thiz, const char* s)
{
	int ret = 0;

	return ret;
}

int RIL_onRequest_dev (RIL* thiz, int request, void *data, size_t datalen, RIL_Token t)
{
	switch (request)
	{
	case RIL_REQUEST_RADIO_POWER:
		requestRadioPower(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_GET_IMEI:
		requestGetImei(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_GET_IMEISV:
		RIL_onRequestComplete(thiz, t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
		//requestGetImeiSv(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_SET_MUTE:
		requestSetMute(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_GET_MUTE:
		requestGetMute(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_RESET_RADIO:
		requestResetRadio(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_BASEBAND_VERSION:
		requestBasebandVersion(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_SET_BAND_MODE:
		requestSetBandMode(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE:
		reqestQueryAvailableBandMode(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_OEM_HOOK_RAW:
		requestOemHookRaw(thiz, data, datalen, t);
		break;

	case RIL_REQUEST_OEM_HOOK_STRINGS:
		requestOemHookStrings(thiz, data, datalen, t);
		break;

	default:
		RIL_onRequestComplete(thiz, t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);
		break;
	}

	return 1;
}


